package cn.fatgod.learn.thymeleaf.ast;

import cn.fatgod.learn.thymeleaf.ast.model.ArgItem;
import cn.fatgod.learn.thymeleaf.ast.model.EnumItem;
import cn.fatgod.learn.thymeleaf.binder.ModelDataBinder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.EnumConstantDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import org.thymeleaf.context.Context;

import java.util.List;
import java.util.Objects;

/**
 * 枚举AST工具
 */
public class EnumAstUtils {

    /**
     * 追加枚举项
     *
     * @param source   源代码
     * @param enumName 枚举名称
     * @param items    枚举项
     * @return 追加枚举项后的Java代码
     */
    public static String appendItem(String source, String enumName, List<EnumItem> items) {
        if (CollUtil.isEmpty(items)) {
            return source;
        }
        TypeDeclaration<?> td = AstUtils.parse(source, enumName.split("\\.")[0]);
        TypeDeclaration<?> enumTd = AstUtils.searchType(td, enumName);
        if (!AstUtils.isEnum(enumTd)) {
            throw new RuntimeException(StrUtil.format("枚举名称{}解析类型为非枚举", enumName));
        }
        boolean present = td.getParentNode().isPresent();
        if (!present) {
            throw new RuntimeException(StrUtil.format("找不到类型{}所在的编译单元", td.toString()));
        }
        EnumDeclaration ed = (EnumDeclaration) enumTd;
        items.stream().map(item -> {
                    EnumConstantDeclaration ecd = new EnumConstantDeclaration()
                            .setName(item.getName());
                    if (StrUtil.isNotBlank(item.getComment())) {
                        ecd.setJavadocComment(item.getComment());
                    }
                    item.getArgs().forEach(arg -> {
                        ecd.addArgument(arg.isStr() ? ("\"" + arg.getVal() + "\"") : arg.getVal());
                    });
                    return ecd;
                }
        ).forEach(ed::addEntry);
        CompilationUnit unit = (CompilationUnit) td.getParentNode().get();
        items.stream().flatMap(item -> item.getArgs().stream())
                .map(ArgItem::getImportPath)
                .filter(StrUtil::isNotBlank)
                .forEach(unit::addImport);
        return AstUtils.beautifyCode(unit);
    }
}